#include "modbus.h"
#include "device.h"
#include "speed_cntr.h"

#define PCA1CPL7    PCA1CPL1
#define PCA1CPH7    PCA1CPH1

#ifdef CODE_VIEW
#define IRP(vector)
#else
#define IRP(vector) interrupt vector
#endif

#define IMP_ISP(vector) void isp_##vector##_imp (void) IRP(vector)
#define NO_IMP_ISP(vector) IMP_ISP(vector) {}

NO_IMP_ISP(INTERRUPT_INT0)
NO_IMP_ISP(INTERRUPT_TIMER0)
NO_IMP_ISP(INTERRUPT_INT1)
NO_IMP_ISP(INTERRUPT_TIMER1)
//NO_IMP_ISP(INTERRUPT_UART0)
NO_IMP_ISP(INTERRUPT_TIMER2)
NO_IMP_ISP(INTERRUPT_SPI0)
NO_IMP_ISP(INTERRUPT_SMBUS0)
NO_IMP_ISP(INTERRUPT_ADC0_WINDOW)
NO_IMP_ISP(INTERRUPT_ADC0_EOC)
NO_IMP_ISP(INTERRUPT_PCA0)
NO_IMP_ISP(INTERRUPT_COMPARATOR0)
NO_IMP_ISP(INTERRUPT_COMPARATOR1)
NO_IMP_ISP(INTERRUPT_TIMER3)
NO_IMP_ISP(INTERRUPT_LIN0)
NO_IMP_ISP(INTERRUPT_VREG)
NO_IMP_ISP(INTERRUPT_CAN0)
NO_IMP_ISP(INTERRUPT_PORT_MATCH)
#ifndef _USES_UART1
NO_IMP_ISP(INTERRUPT_UART1)
#endif
//NO_IMP_ISP(INTERRUPT_PCA1)
NO_IMP_ISP(INTERRUPT_COMPARATOR2)
//NO_IMP_ISP(INTERRUPT_TIMER4)
//NO_IMP_ISP(INTERRUPT_TIMER5)

UU16 data system_tick = {0};

#pragma disable
ushort SystemTickLow()
{
    ushort tick;
    uchar current = SFRPAGE;
    SFRPAGE = ACTIVE2_PAGE;
    tick = PCA1;
    SFRPAGE = current;
    return tick;
}

ushort SystemTickHigh()
{
    uchar hi, lo;

    do
    {
        hi = system_tick.U8[MSB];
        lo = system_tick.U8[LSB];
    }
    while(hi != system_tick.U8[MSB]);

    return (ushort)hi << 8 | lo;
}

ulong SystemTick()
{
    ushort hi, lo;
    do
    {
        hi = SystemTickHigh();
        lo = SystemTickLow();
    }
    while(hi != SystemTickHigh());

    return (ulong)hi << 16 | lo;
}

void Delay_Tick(ushort tick)
{
    ushort t = SystemTickLow();
    while(SystemTickLow() - t < tick);
}

void Delay_Tick_Event(ulong tick)
{
    ulong t = SystemTick();
    while(SystemTick() - t < tick)
        Main_Loop();
}

// Uart0 发送/接收中断
IMP_ISP(INTERRUPT_UART0)
{
    if (RI0)
    {
        uart0_rx_pending = 1;

        SFRPAGE = ACTIVE2_PAGE;
        if (CCF6)
            uart0_len = 0;

        uart0_timestamp = SystemTickLow() + ONE_MS;
        PCA1CPL6 = uart0_timestamp;
        PCA1CPH6 = uart0_timestamp >> 8;
        CCF6 = 0;
        SFRPAGE = ACTIVE_PAGE;

        do
        {
            RI0 = 0;
            uart0_buf[UART0_BUF_MASK & uart0_len++] = SBUF0;
        }
        while(RI0);

        if (SCON0 & 0x80)
        {
            SCON0 &= ~0x80;
            ++bus_char_overrun_count;
        }

        uart0_timestamp = SystemTickLow();
    }

    if (TI0)
    {
        TI0 = 0;
        if (uart0_len)
        {
            SBUF0 = *uart0_tx_ptr++;
            --uart0_len;
        }
        else
        {
            uart0_tx_pending = 0;
            REN0 = 1;
        }
    }
}
#ifdef _USES_UART1
// Uart1 发送/接收中断
IMP_ISP(INTERRUPT_UART1)
{
    if (SCON1 & 0x01)
    {
        // 如果距上次接收超过1ms, 重新接收
        if (CCF7)
            uart1_rx_len = 0;

        // 设置1ms超时
        uart1_timestamp = SystemTickLow() + ONE_MS;
        PCA1CPL7 = uart1_timestamp;
        PCA1CPH7 = uart1_timestamp >> 8;
        CCF7 = 0;

        uart1_timestamp = SystemTickLow();

        do
        {
            SCON1 &= ~0x01;
            uart1_rx_buf[UART1_BUF_MASK & uart1_rx_len++] = SBUF1;
        }
        while(SCON1 & 0x01);
    }

    if (SCON1 & 0x02)
    {
        SCON1 &= ~0x02;
        if (uart1_tx_left)
        {
            SBUF1 = *uart1_tx_ptr++;
            --uart1_tx_left;
        }
        else
        {
            // 设置10ms超时
            uart1_timestamp = SystemTickLow() + _15_MS;
            PCA1CPL7 = uart1_timestamp;
            PCA1CPH7 = uart1_timestamp >> 8;
            CCF7 = 0;

            uart1_tx_pending = 0;
            uart1_rx_pending = 1;
            uart1_timestamp = SystemTickLow();
        }
    }
}
#endif
IMP_ISP(INTERRUPT_PCA1)
{
    if (CF1)
    {
        CF1 = 0;
        ++system_tick.U16;
    }
}

//计数溢出中断
IMP_ISP(INTERRUPT_TIMER4)
{
    TMR4CN &= ~0x80;
    speed_cntr_update(&srd_y);
}

IMP_ISP(INTERRUPT_TIMER5)
{
#if (PCB_VERSION == PCB_A2)
    bit flag;
#endif
    TMR5CN  &= ~0x80;
#if (PCB_VERSION == PCB_A2)
    SFRPAGE = CONFIG_PAGE;
    flag = P3SKIP;
    SFRPAGE = ACTIVE_PAGE;
    if(flag)
        speed_cntr_update(&srd_m);
    else
#endif
        speed_cntr_update(&srd_z);
}
